package cn.yh.nft.turbo.collection.domain.service.impl.es;

import cn.yh.nft.turbo.base.response.PageResponse;
import cn.yh.nft.turbo.collection.domain.entity.Collection;
import cn.yh.nft.turbo.collection.domain.service.impl.BaseCollectionService;
import cn.yh.nft.turbo.collection.infrastructure.es.mapper.CollectionEsMapper;
import com.google.common.collect.ImmutableList;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.dromara.easyes.core.biz.SAPageInfo;
import org.dromara.easyes.core.conditions.select.LambdaEsQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.Query;
import org.springframework.stereotype.Service;

/**
 *  ES的查询藏品服务
 * @ClassName: CollectionEsService
 * @Author: 草莓爱上啵啵
 */
@Service
@ConditionalOnProperty(name = "spring.elasticsearch.enable", havingValue = "true")
public class CollectionEsService extends BaseCollectionService {

    @Autowired
    private ElasticsearchOperations elasticsearchOperations;

    @Autowired
    private CollectionEsMapper collectionEsMapper;

    /**
 * 根据状态分页查询收藏品信息
 *
 * @param name 收藏品名称，用于精确查询
 * @param state 收藏品的状态，用于筛选查询结果
 * @param currentPage 当前页码，用于分页查询
 * @param pageSize 每页记录数，用于分页查询
 * @return 返回一个包含查询结果的PageResponse对象
 */
@Override
public PageResponse<Collection> pageQueryByState(String name, String state, int currentPage, int pageSize) {
    // 初始化查询条件
    Criteria criteria = null;
    // 如果名称不为空，则添加名称作为查询条件
    if (StringUtils.isNotBlank(name)) {
        criteria = new Criteria("name").is(name).and(new Criteria("state").is(state), new Criteria("deleted").is("0"));
    } else {
        // 如果名称为空，仅根据状态进行查询，并确保记录未被删除
        criteria = new Criteria("state").is(state).and(new Criteria("deleted").is("0"));
    }

    // 创建分页请求对象，注意页码从0开始，因此需要减1
    PageRequest pageRequest = PageRequest.of(currentPage - 1, pageSize);

    // 创建查询对象，设置查询条件和分页请求，并按创建时间升序排序
    Query query = new CriteriaQuery(criteria).setPageable(pageRequest).addSort(Sort.by(Sort.Order.asc("create_time")));

    // 执行查询，获取搜索结果
    SearchHits<Collection> searchHits = elasticsearchOperations.search(query, Collection.class);

    // 将搜索结果转换为指定的PageResponse对象并返回
    return PageResponse.of(searchHits.getSearchHits().stream().map(SearchHit::getContent).toList(),(int) searchHits.getTotalHits(),pageSize, currentPage);
}


    /**
 * 根据名称和状态进行深度分页查询
 *
 * 该方法用于在Elasticsearch中根据藏品的名称和状态进行深度分页查询深度分页是一种提高查询效率的技术，
 * 特别适用于数据量大、分页深的场景通过使用search_after方法代替传统的from/size分页，
 * 能够更高效地跳过大量无关文档，直接定位到所需结果
 *
 * @param name 藏品名称，用于查询
 * @param state 藏品状态，用于查询
 * @param pageSize 每页大小，决定每次返回的结果数量
 * @param lastId 上一次查询结果中的最后一条记录的ID，用于定位下一页的起始位置
 * @return 返回包含藏品信息的SAPageInfo对象
 */
public SAPageInfo<Collection> deepPageQueryByState(String name, String state, int pageSize, Long lastId){
    // 创建查询条件包装器
    LambdaEsQueryWrapper<Collection> queryWrapper = new LambdaEsQueryWrapper<>();
    // 匹配藏品名称
    queryWrapper.match(Collection::getName, name)
            // 并且匹配藏品状态和删除标志
            .and(wrapper -> wrapper
                    .match(collection -> collection.getState().name(), state)
                    .match(Collection::getDeleted, "0"))
            // 按创建时间升序排序
            .orderByAsc("create_time");

    SAPageInfo<Collection> saPageInfo;
    // 根据lastId是否为空，决定使用不同的分页查询策略
    if (lastId == null) {
        // 如果lastId为空，表示是第一页查询，不需要search_after参数
        saPageInfo = collectionEsMapper.searchAfterPage(queryWrapper, null, pageSize);
    } else {
        // 如果lastId不为空，使用search_after参数进行深度分页查询，固定每页大小为10
        saPageInfo = collectionEsMapper.searchAfterPage(queryWrapper, ImmutableList.of(lastId), 10);
    }
    // 返回查询结果
    return saPageInfo;

}

}
